home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / amiga / viewers / mpgplyr1.lha / src / fs2.c < prev    next >
C/C++ Source or Header  |  1992-12-08  |  9KB  |  391 lines

  1. /*
  2.  * Copyright (c) 1992 The Regents of the University of California.
  3.  * All rights reserved.
  4.  * 
  5.  * Permission to use, copy, modify, and distribute this software and its
  6.  * documentation for any purpose, without fee, and without written agreement is
  7.  * hereby granted, provided that the above copyright notice and the following
  8.  * two paragraphs appear in all copies of this software.
  9.  * 
  10.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  11.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  12.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  13.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14.  * 
  15.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  16.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  17.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  18.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  19.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  20.  */
  21. #include "video.h"
  22. #include "dither.h"
  23. #include "fs2.h"
  24.  
  25. /* Structures for precomputed error propogation values. */
  26.  
  27. static FS2DithVal lum_index[256];
  28. static FS2DithVal cr_index[256];
  29. static FS2DithVal cb_index[256];
  30.  
  31.  
  32.  
  33. /*
  34.  *--------------------------------------------------------------
  35.  *
  36.  * InitFS2Dither --
  37.  *
  38.  *    Initializes structures for precomputed 2 error f-s dithering.
  39.  *      The value field of the structure contains the pixel component 
  40.  *      of the particular channel in question. Thus the addition of
  41.  *      the value field of a structure in the luminance index, a 
  42.  *      structure in the Cr index, and a structure in the Cb index will
  43.  *      yeild a color number. This color number can then be transformed
  44.  *      into a pixel value to be displayed. Each channel can then be
  45.  *      processed (i.e. dithered) separately, with the results being
  46.  *      added up and remapped to yield a final pixel value.
  47.  *
  48.  * Results:
  49.  *    None.
  50.  *
  51.  * Side effects:
  52.  *      None.
  53.  *
  54.  *--------------------------------------------------------------
  55.  */
  56.  
  57. void InitFS2Dither()
  58. {
  59.   int i;
  60.  
  61.   /* For each possible pixel value, precompute propogated error and
  62.      store in array.
  63.   */
  64.   
  65.   for (i=0; i<256; i++) {
  66.     lum_index[i].value = (i * LUM_RANGE) / 256;
  67.  
  68.     lum_index[i].e1 = (i-lum_values[lum_index[i].value]) / 2;
  69.     lum_index[i].e3 = (i - lum_values[lum_index[i].value]) - lum_index[i].e1;
  70.  
  71.     lum_index[i].value *= LUM_BASE;
  72.  
  73.     cr_index[i].value = (i * CR_RANGE) / 256; 
  74.  
  75.     cr_index[i].e1 = (i - cr_values[cr_index[i].value]) / 2;
  76.     cr_index[i].e3 = (i - cr_values[cr_index[i].value]) - cr_index[i].e1 ;
  77.  
  78.     cr_index[i].value *= CR_BASE;
  79.  
  80.     cb_index[i].value = (i * CB_RANGE) / 256; 
  81.  
  82.     cb_index[i].e1 = (i - cb_values[cb_index[i].value]) / 2;
  83.     cb_index[i].e3 = (i - cb_values[cb_index[i].value]) - cb_index[i].e1;
  84.  
  85.     cb_index[i].value *= CB_BASE;
  86.  
  87.   }
  88.  
  89. }
  90.  
  91.  
  92. /*
  93.  *--------------------------------------------------------------
  94.  *
  95.  * DitherImage --
  96.  *
  97.  *    Converts lum, cr, cb image planes into fixed colormap
  98.  *      space.
  99.  *
  100.  * Results:
  101.  *    the display plane is replaced by 8-bit colormap space
  102.  *      image.
  103.  *
  104.  * Side effects:
  105.  *      Hopefully, none.
  106.  *
  107.  *--------------------------------------------------------------
  108.  */
  109.  
  110. void FS2DitherImage(lum, cr, cb, disp, rows, cols)
  111.      unsigned char *lum, *cr, *cb, *disp;
  112.      int rows, cols;
  113. {
  114.   static char *cur_row_error, *next_row_error;
  115.   static int first = 1;
  116.   char  *cur_row_err_mark, *next_row_err_mark;
  117.   char *temp;
  118.   int i, j, pixsum, c_cols;
  119.   unsigned char *cur_row, *channel, *dest_row;
  120.   FS2DithVal *chan_index;
  121.  
  122.   /* Allocate error arrays. */
  123.  
  124.   if (first) {
  125.     cur_row_error = (char *) malloc(cols+2);
  126.     next_row_error = (char *) malloc(cols+2);
  127.     first = 0;
  128.   }
  129.  
  130.   /* Initialize error arrays. */
  131.  
  132.   memset(cur_row_error, 0, cols+2);
  133.   memset(next_row_error, 0, cols+2);
  134.  
  135.   /* Use luminance values first. */
  136.  
  137.   /* For each two rows, do... */
  138.  
  139.   for(i=0; i<rows; i+=2) {
  140.  
  141.     /* Establish pointer to current source and destination rows. */
  142.     cur_row = lum + (i*cols);
  143.     dest_row = disp + (i*cols);
  144.  
  145.     /* Establish pointers to error arrays. */
  146.     cur_row_err_mark = cur_row_error + 1;
  147.     next_row_err_mark = next_row_error + 1;
  148.  
  149.     
  150.     /* For each column within first row do... */
  151.  
  152.     for (j=0; j<cols; j++) {
  153.  
  154.       /* Calculate pixel value with error. */
  155.  
  156.       pixsum = *cur_row + *cur_row_err_mark;
  157.  
  158.       /* Bounds check. */
  159.       if (pixsum < 0) pixsum = 0;
  160.       else if (pixsum > 255) pixsum = 255;
  161.  
  162.       /* Establish dest value, propogate errors. */
  163.  
  164.       *dest_row = lum_index[pixsum].value;
  165.       *(cur_row_err_mark+1) += lum_index[pixsum].e1; 
  166.       *next_row_err_mark += lum_index[pixsum].e3; 
  167.  
  168.       /* Advance pointers. */
  169.  
  170.       cur_row++;
  171.       dest_row++;
  172.       cur_row_err_mark++;
  173.       next_row_err_mark++;
  174.     }
  175.  
  176.     /* Switch error arrays, so next row errors are now current row errors, and
  177.        vice versa. 
  178.     */
  179.  
  180.     temp = cur_row_error;
  181.     cur_row_error = next_row_error;
  182.     next_row_error = temp;
  183.  
  184.     /* Reset next row errors. */
  185.  
  186.     memset(next_row_error, 0, cols+2); 
  187.  
  188.     /* Establish pointers for second row. This one will be processed right to
  189.        left to establish serpantine motion.
  190.     */
  191.  
  192.     cur_row += cols-1;
  193.     dest_row += cols-1;
  194.     cur_row_err_mark = cur_row_error + cols;
  195.     next_row_err_mark = next_row_error + cols;
  196.  
  197.     /* Process each column... */
  198.  
  199.     for (j=0; j<cols; j++) {
  200.  
  201.       pixsum = *cur_row + *cur_row_err_mark;
  202.       if (pixsum < 0) pixsum = 0;
  203.       else if (pixsum > 255) pixsum = 255;
  204.       
  205.       *dest_row = lum_index[pixsum].value;
  206.       *(cur_row_err_mark-1) += lum_index[pixsum].e1; 
  207.       *next_row_err_mark += lum_index[pixsum].e3; 
  208.       
  209.       cur_row--;
  210.       dest_row--;
  211.       cur_row_err_mark--;
  212.       next_row_err_mark--;
  213.     }
  214.  
  215.     /* Switch error arrays. */
  216.  
  217.     temp = cur_row_error;
  218.     cur_row_error = next_row_error;
  219.     next_row_error = temp;
  220.  
  221.     /* Reset next row errors. */
  222.  
  223.     memset(next_row_error, 0, cols+2); 
  224.   }
  225.  
  226.   /* Reset error arrays. */
  227.  
  228.   memset(cur_row_error, 0, cols+2); 
  229.   
  230.   /* Establish column length divided by two. */
  231.  
  232.   c_cols = cols >> 1;
  233.  
  234.   /* Set channel to Cr. Use Cr index. */
  235.  
  236.   channel = cr;
  237.   chan_index = cr_index;
  238.   
  239.  repeat:
  240.  
  241.   /* Process each row of chrominance data... */
  242.  
  243.   for (i=0; i < rows; i+=2) {
  244.  
  245.     /* Establish pointers. */
  246.  
  247.     cur_row = channel + ((i>>1)*c_cols);
  248.     dest_row = disp + (i*cols);
  249.  
  250.     cur_row_err_mark = cur_row_error+1;
  251.     next_row_err_mark = next_row_error+1;
  252.  
  253.     /* For each column in row... */
  254.  
  255.     for (j=0; j<cols; j++) {
  256.       int p_val;
  257.  
  258.       /* Get pixel value as twos bit complement. */
  259.  
  260.       p_val = *cur_row;
  261.  
  262.       /* Add error term. */
  263.  
  264.       pixsum = *cur_row_err_mark + p_val;
  265.  
  266.       /* Bounds check. */
  267.  
  268.       if (pixsum < 0) pixsum = 0;
  269.       else if (pixsum > 255) pixsum = 255;
  270.  
  271.       /* Increment dest value. */
  272.  
  273.       *dest_row += chan_index[pixsum].value;
  274.  
  275.       /* Propogate error values. */
  276.  
  277.       *(cur_row_err_mark+1) += chan_index[pixsum].e1; 
  278.       *next_row_err_mark += chan_index[pixsum].e3; 
  279.  
  280.  
  281.       /* If count is odd, advance source pointer (Cr and Cb channels are 2:1 
  282.      subsampled.
  283.       */
  284.  
  285.       if (j&1) cur_row++;
  286.  
  287.       /* Advance destination and error pointers. */
  288.  
  289.       dest_row++;
  290.       cur_row_err_mark++;
  291.       next_row_err_mark++;
  292.     }
  293.  
  294.     /* Switch error arrays. */
  295.  
  296.     temp = cur_row_error;
  297.     cur_row_error = next_row_error;
  298.     next_row_error = temp;
  299.  
  300.     /* Reset next row errors. */
  301.  
  302.     memset(next_row_error, 0, cols+2);
  303.  
  304.     /* Re-establish pointers. */
  305.  
  306.     cur_row += c_cols-1;
  307.     dest_row += cols-1;
  308.     cur_row_err_mark = cur_row_error+cols;
  309.     next_row_err_mark = next_row_error+cols;
  310.  
  311.     /* Process second row right to left. */
  312.  
  313.     for (j=0; j<cols; j++) {
  314.       int p_val;
  315.  
  316.       /* Get source value as twos bit complement. */
  317.  
  318.       p_val = *cur_row;
  319.  
  320.       /* Add error. */
  321.  
  322.       pixsum = *cur_row_err_mark + p_val;
  323.  
  324.       /* Bounds check. */
  325.  
  326.       if (pixsum < 0) pixsum = 0;
  327.       else if (pixsum > 255) pixsum = 255;
  328.  
  329.       /* Increment dest value. */
  330.  
  331.       *dest_row += chan_index[pixsum].value;
  332.  
  333.       /* Propogate errors. */
  334.  
  335.       *(cur_row_err_mark-1) += chan_index[pixsum].e1; 
  336.       *next_row_err_mark += chan_index[pixsum].e3; 
  337.  
  338.       /* If column counters is odd, decrement source pointer. */
  339.  
  340.       if (j&1) cur_row--;
  341.  
  342.       /* Decrement dest and error pointers. */
  343.  
  344.       dest_row--;
  345.       cur_row_err_mark--;
  346.       next_row_err_mark--;
  347.     }
  348.  
  349.     /* Switch error arrays. */
  350.  
  351.     temp = cur_row_error;
  352.     cur_row_error = next_row_error;
  353.     next_row_error = temp;
  354.  
  355.     /* Reinitialize next row errors. */
  356.  
  357.     memset(next_row_error, 0, cols+2);
  358.   }
  359.  
  360.   /* If Cr channel completed, set channel to Cb and Cb index and repeat. */
  361.  
  362.   if (channel == cr) {
  363.     channel = cb;
  364.     chan_index = cb_index;
  365.     memset(cur_row_error, 0, cols+2);
  366.  
  367.     goto repeat;
  368.   }
  369.  
  370.   /* Establish pointer to start of display frame. */
  371.  
  372.   dest_row = disp;
  373.  
  374.   /* Transform all display values to pixel values. */
  375.  
  376.   for (i=0; i<rows; i++) {
  377.     for (j=0; j<cols; j++) {
  378.       *dest_row =  pixel[*dest_row];
  379.       dest_row++;
  380.     }
  381.   }
  382. }
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.